using System;
using System.Collections.Generic;
using System.Management;
using System.Security.Principal;
using Microsoft.Win32;
using Newtonsoft.Json;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;

namespace demo
{
    /// <summary>
    /// 已安装软件信息获取工具类
    /// 用于获取Windows系统中已安装的软件列表
    /// </summary>
    public class InstalledSoftwareHelper
    {
        /// <summary>
        /// 获取系统已安装软件列表的JSON字符串
        /// </summary>
        /// <returns>包含软件列表信息的JSON字符串</returns>
        public static string GetInstalledSoftwareJson()
        {
            try
            {
                var networkInfo = GetNetworkInfo();
                var result = new
                {
                    CollectionTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    ComputerName = Environment.MachineName,
                    HasAdminRights = IsRunningAsAdministrator(),
                    IPAddress = networkInfo.IPAddress,
                    MACAddress = networkInfo.MACAddress,
                    SoftwareList = GetInstalledSoftwareList(),
                    TotalCount = 0,
                    Message = ""
                };

                // 更新总数和消息
                var finalResult = new
                {
                    result.CollectionTime,
                    result.ComputerName,
                    result.HasAdminRights,
                    result.IPAddress,
                    result.MACAddress,
                    result.SoftwareList,
                    TotalCount = result.SoftwareList?.Count ?? 0,
                    Message = result.HasAdminRights ? "成功获取软件列表" : "权限不足，可能无法获取完整的软件列表"
                };

                return JsonConvert.SerializeObject(finalResult, Formatting.Indented);
            }
            catch (Exception ex)
            {
                var networkInfo = GetNetworkInfo();
                var errorResult = new
                {
                    CollectionTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    ComputerName = Environment.MachineName,
                    HasAdminRights = IsRunningAsAdministrator(),
                    IPAddress = networkInfo.IPAddress,
                    MACAddress = networkInfo.MACAddress,
                    SoftwareList = new List<object>(),
                    TotalCount = 0,
                    Message = $"获取软件列表失败: {ex.Message}",
                    Error = ex.ToString()
                };

                return JsonConvert.SerializeObject(errorResult, Formatting.Indented);
            }
        }

        /// <summary>
        /// 获取网络信息（IP地址和MAC地址）
        /// </summary>
        /// <returns>包含IP地址和MAC地址的对象</returns>
        private static dynamic GetNetworkInfo()
        {
            try
            {
                string ipAddress = "未知";
                string macAddress = "未知";

                // 获取本机IP地址
                try
                {
                    var host = Dns.GetHostEntry(Dns.GetHostName());
                    foreach (var ip in host.AddressList)
                    {
                        if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {
                            ipAddress = ip.ToString();
                            break;
                        }
                    }
                }
                catch
                {
                    ipAddress = "获取失败";
                }

                // 获取MAC地址
                try
                {
                    foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
                    {
                        if (nic.OperationalStatus == OperationalStatus.Up &&
                            nic.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
                            nic.NetworkInterfaceType != NetworkInterfaceType.Tunnel)
                        {
                            var macBytes = nic.GetPhysicalAddress().GetAddressBytes();
                            if (macBytes.Length > 0)
                            {
                                macAddress = string.Join(":", macBytes.Select(b => b.ToString("X2")));
                                break;
                            }
                        }
                    }
                }
                catch
                {
                    macAddress = "获取失败";
                }

                return new
                {
                    IPAddress = ipAddress,
                    MACAddress = macAddress
                };
            }
            catch
            {
                return new
                {
                    IPAddress = "获取失败",
                    MACAddress = "获取失败"
                };
            }
        }

        /// <summary>
        /// 检查当前程序是否以管理员权限运行
        /// </summary>
        /// <returns>如果是管理员权限返回true，否则返回false</returns>
        public static bool IsRunningAsAdministrator()
        {
            try
            {
                WindowsIdentity identity = WindowsIdentity.GetCurrent();
                WindowsPrincipal principal = new WindowsPrincipal(identity);
                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取已安装软件列表
        /// </summary>
        /// <returns>软件信息列表</returns>
        private static List<object> GetInstalledSoftwareList()
        {
            var softwareList = new List<object>();

            try
            {
                // 方法1：通过注册表获取（32位和64位程序）
                var registrySoftware = GetSoftwareFromRegistry();
                softwareList.AddRange(registrySoftware);

                // 方法2：通过WMI获取（需要管理员权限）
                if (IsRunningAsAdministrator())
                {
                    var wmiSoftware = GetSoftwareFromWMI();

                    // 合并WMI结果，避免重复
                    foreach (var wmiItem in wmiSoftware)
                    {
                        var wmiSoft = wmiItem as dynamic;
                        bool isDuplicate = false;

                        foreach (var regItem in registrySoftware)
                        {
                            var regSoft = regItem as dynamic;
                            if (regSoft.Name == wmiSoft.Name ||
                                (regSoft.Name.Contains(wmiSoft.Name) || wmiSoft.Name.Contains(regSoft.Name)))
                            {
                                isDuplicate = true;
                                break;
                            }
                        }

                        if (!isDuplicate)
                        {
                            softwareList.Add(wmiItem);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // 如果获取失败，返回错误信息
                softwareList.Add(new
                {
                    Name = "获取软件列表时发生错误",
                    Version = "",
                    Publisher = "",
                    InstallDate = "",
                    InstallLocation = "",
                    Source = "Error",
                    Error = ex.Message
                });
            }

            // 按软件名称排序
            return softwareList.OrderBy(s => ((dynamic)s).Name).ToList();
        }

        /// <summary>
        /// 通过注册表获取已安装软件信息
        /// </summary>
        /// <returns>软件信息列表</returns>
        private static List<object> GetSoftwareFromRegistry()
        {
            var softwareList = new List<object>();

            try
            {
                // 64位系统的注册表路径
                string[] registryPaths = {
                    @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
                    @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
                };

                foreach (string path in registryPaths)
                {
                    try
                    {
                        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(path))
                        {
                            if (key != null)
                            {
                                foreach (string subKeyName in key.GetSubKeyNames())
                                {
                                    try
                                    {
                                        using (RegistryKey subKey = key.OpenSubKey(subKeyName))
                                        {
                                            if (subKey != null)
                                            {
                                                string displayName = subKey.GetValue("DisplayName")?.ToString();

                                                // 过滤掉系统组件和更新
                                                if (!string.IsNullOrWhiteSpace(displayName) &&
                                                    !displayName.StartsWith("Security Update") &&
                                                    !displayName.StartsWith("Update for") &&
                                                    !displayName.Contains("Hotfix") &&
                                                    subKey.GetValue("SystemComponent") == null)
                                                {
                                                    var software = new
                                                    {
                                                        Name = displayName,
                                                        Version = subKey.GetValue("DisplayVersion")?.ToString() ?? "",
                                                        Publisher = subKey.GetValue("Publisher")?.ToString() ?? "",
                                                        InstallDate = FormatInstallDate(subKey.GetValue("InstallDate")?.ToString()),
                                                        InstallLocation = subKey.GetValue("InstallLocation")?.ToString() ?? "",
                                                        Source = path.Contains("WOW6432Node") ? "Registry-32bit" : "Registry-64bit"
                                                    };

                                                    softwareList.Add(software);
                                                }
                                            }
                                        }
                                    }
                                    catch
                                    {
                                        // 忽略单个软件项的错误
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                    catch
                    {
                        // 忽略注册表路径访问错误
                        continue;
                    }
                }
            }
            catch (Exception ex)
            {
                softwareList.Add(new
                {
                    Name = "注册表访问错误",
                    Version = "",
                    Publisher = "",
                    InstallDate = "",
                    InstallLocation = "",
                    Source = "Registry-Error",
                    Error = ex.Message
                });
            }

            return softwareList;
        }

        /// <summary>
        /// 通过WMI获取已安装软件信息（需要管理员权限）
        /// </summary>
        /// <returns>软件信息列表</returns>
        private static List<object> GetSoftwareFromWMI()
        {
            var softwareList = new List<object>();

            try
            {
                using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Product"))
                {
                    foreach (ManagementObject obj in searcher.Get())
                    {
                        try
                        {
                            string name = obj["Name"]?.ToString();
                            if (!string.IsNullOrWhiteSpace(name))
                            {
                                var software = new
                                {
                                    Name = name,
                                    Version = obj["Version"]?.ToString() ?? "",
                                    Publisher = obj["Vendor"]?.ToString() ?? "",
                                    InstallDate = FormatInstallDate(obj["InstallDate"]?.ToString()),
                                    InstallLocation = obj["InstallLocation"]?.ToString() ?? "",
                                    Source = "WMI"
                                };

                                softwareList.Add(software);
                            }
                        }
                        catch
                        {
                            // 忽略单个软件项的错误
                            continue;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                softwareList.Add(new
                {
                    Name = "WMI查询错误（可能需要管理员权限）",
                    Version = "",
                    Publisher = "",
                    InstallDate = "",
                    InstallLocation = "",
                    Source = "WMI-Error",
                    Error = ex.Message
                });
            }

            return softwareList;
        }

        /// <summary>
        /// 格式化安装日期
        /// </summary>
        /// <param name="installDate">原始安装日期字符串</param>
        /// <returns>格式化后的日期字符串</returns>
        private static string FormatInstallDate(string installDate)
        {
            if (string.IsNullOrWhiteSpace(installDate))
                return "";

            try
            {
                // 处理注册表中的日期格式 (YYYYMMDD)
                if (installDate.Length == 8 && int.TryParse(installDate, out _))
                {
                    string year = installDate.Substring(0, 4);
                    string month = installDate.Substring(4, 2);
                    string day = installDate.Substring(6, 2);
                    return $"{year}-{month}-{day}";
                }

                // 处理WMI中的日期格式
                if (installDate.Length >= 8)
                {
                    DateTime date;
                    if (DateTime.TryParse(installDate, out date))
                    {
                        return date.ToString("yyyy-MM-dd");
                    }
                }

                return installDate;
            }
            catch
            {
                return installDate;
            }
        }
    }
}